package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"runtime"
	"runtime/debug"
)

func main() {
	defer func() {
		if e := recover(); e != nil {
			fmt.Println("shang", string(debug.Stack()))
		}
	}()
	runTest()
	run1Test()
}

func run1Test() {

	err := errors.New("sss")
	s := fmt.Sprintf("%s,%s", err.Error(), debug.Stack())
	fmt.Println(s)
}

func runTest() {
	defer func() {
	}()
	err := errors.New("sss")
	err = warpError("test", err)
	panic(err)
}

func t1() (str string, err error) {
	return "123", errors.New("tets")
}

func warpError(msg string, err error) error {
	pc, file, line, ok := runtime.Caller(1)
	f := runtime.FuncForPC(pc)
	if !ok {
		return errors.New("wrapError")
	}
	if err == nil {
		return nil
	}
	errMsg := fmt.Sprintf("%s at %s %d (method %s)\n Cause by %s\n", msg, file, line, f.Name(), err.Error())
	return errors.New(errMsg)
}

func run() error {
	err := &ErrInfo{}
	err.Code = 400
	err.Msg = "test"
	return err
}

func test() {
	//err := errors.New("this a test")
	debug.PrintStack()
}

type ErrInfo struct {
	Code int
	Msg  string
}

func (e ErrInfo) Error() string {
	res, _ := json.Marshal(e)
	return string(res)
}
